package wcg;

import ikelib.wintime;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

//Origin Time       2011/03/11 14:46:00
//Lat.              38.103
//Long.             142.860
//Depth. (km)       24
//Mag.              9.0
//Station Code      YMT017
//Station Lat.      38.7909
//Station Long.     140.3130
//Station Height(m) -9999
//Record Time       2011/03/11 14:47:03
//Sampling Freq(Hz) 100Hz
//Duration Time(s)  300
//Dir.              U-D
//Scale Factor      3920(gal)/6182761
//Max. Acc. (gal)   47.334
//Last Correction   2011/03/11 14:46:48
//Memo.             
//     559      566      563      554      558      561      559      560 
//     561      564      559      550      551      558      558      553 
//     552      552      552      557      557      551      551      555 

public class KNET_ascii {
	
	public float Latitude = 0f;		// 局の緯度
	public float Longitude = 0f;	// 局の経度
	public float Altitude = 0f;		// 局の高度
	public int SampleRate = 0;		// サンプリングレート
	public int Duration = 0;		// 時間
	public String StationCode = new String("Test");	// 局のコード
	public String Dir = new String("U-D");			// 方向
	public wintime StartTime = null;	// データの時刻
	public double ScaleFactor = 0.0;	// 	デジットあたりの物理量
	public String Unit = null;			// 物理単位 文字列
	public int 	FullScale=0;			// フルスケール
	public int[] Data = null;
	public int Channel=0xff00;			// StationCode,Dirから作成されるCH ID (0xfXXY) 
	private boolean bChannelReserve=false;	// ＣｈａｎｎｅｌＩＤが指定されているので自動生成しない。
	/**
	 * 
	 */
	KNET_ascii(){
		
	}
	/**
	 * ファイルから読み出して構築
	 * @param file
	 */
	KNET_ascii(String file){
		if(load(file)==0){
			makeChannelID();
		}
	}
	/**
	 * byte[] から構築
	 * @param c
	 */
	KNET_ascii(byte[] c){
		if(load(c)==0){
			makeChannelID();
		}
	}
	
	/**
	 * ヘッダーを読み出す
	 * @param str
	 * @return
	 */
	private int loadHeader(String str){
		int ret = 0;
		// 19文字目以降がデータ
		if(str.length()>=18){
			String field = str.substring(0,17);
			field = field.trim();
			if(0==field.compareToIgnoreCase("Origin Time")){
			}
			// K-net AsciiにはないがＣｈａｎｎｅｌＩＤを直接してできるようにするために
			else if(0==field.compareToIgnoreCase("Channel ID")){
				String dat = str.substring(18).trim();
				if(dat != null && !dat.isEmpty() ){
					Channel = Integer.parseInt(dat,16);
					bChannelReserve=true;
				}
				
			}
			else if(0==field.compareToIgnoreCase("Lat.")){
			}
			else if(0==field.compareToIgnoreCase("Long.")){
			}
			else if(0==field.compareToIgnoreCase("Depth. (km)")){
			}
			else if(0==field.compareToIgnoreCase("Mag.")){
			}
			else if(0==field.compareToIgnoreCase("Station Code")){
				String dat = str.substring(18).trim();
				if(dat!=null){
					StationCode=dat;
				}
				else{
					System.out.println("Use default station name : NoName");
				}
			}
			else if(0==field.compareToIgnoreCase("Station Lat.")){
				String dat = str.substring(18).trim();
				if(dat != null && !dat.isEmpty()){
						Latitude = Float.valueOf(dat);
				}
				else{
					System.out.println("Use default Latitude : 0");
					Latitude = 0f;
				}
			}
			else if(0==field.compareToIgnoreCase("Station Long.")){
				String dat = str.substring(18).trim();
				if(dat != null && !dat.isEmpty()){
					Longitude = Float.valueOf(dat);
				}
				else{
					System.out.println("Use default Longitude : 0");
					Longitude = 0f;
				}
			}
			else if(0==field.compareToIgnoreCase("Station Height(m)")){
				String dat = str.substring(18).trim();
				if(dat != null && !dat.isEmpty()){
					Altitude = Float.valueOf(dat);
				}
				else{
					System.out.println("Use default Altitude : 0");
					Altitude = 0f;
				}
			}
			else if(0==field.compareToIgnoreCase("Record Time")){
				String dat = str.substring(18).trim();
				if(StartTime==null) StartTime = new wintime(2000,1,1,0,0,0);
				if(dat != null && !dat.isEmpty()){
					StartTime.parseDaySec(dat);
				}
				else{
					System.out.println("Use default Record time : " + StartTime.fmt());
				}
			}
			else if(0==field.compareToIgnoreCase("Sampling Freq(Hz)")){
				String dat = str.substring(18).trim();
				if(dat != null && !dat.isEmpty()){
					if(dat.substring(dat.length()-2,dat.length()).compareToIgnoreCase("Hz")==0){
						dat = dat.substring(0,dat.length()-2);
					}
					SampleRate = Integer.valueOf(dat);
				}
				else{
					System.out.println("Use default Record time : xxxxx");
					SampleRate = 100;
				}
			}
			else if(0==field.compareToIgnoreCase("Duration Time(s)")){
				String dat = str.substring(18).trim();
				if(dat != null && !dat.isEmpty() ){
					Duration = Integer.valueOf(dat);
				}
				else{
					System.out.println("Use default Duration time : 0");
					Duration = 0;
				}
			}
			else if(0==field.compareToIgnoreCase("Dir.")){
				String dat = str.substring(18).trim();
				Dir=dat;
			}
			else if(0==field.compareToIgnoreCase("Scale Factor")){
				String dat = str.substring(18).trim();
				if(dat != null && !dat.isEmpty()){
					String[] tok = dat.split("[()/]");
					if(tok.length==4){
						int num = Integer.valueOf(tok[0]);
						int den = Integer.valueOf(tok[3]);
						ScaleFactor = (double)num/(double)den;
						FullScale=den;
						Unit = tok[1];
					}
					else{
						System.out.println("Use default Scale factor : 2000, fullscale 8388608 , unit gal");
						ScaleFactor = 2000;
						FullScale = 8388608;
						Unit = "gal";
					}
				}
				else{
					System.out.println("Use default Scale factor : 2000, fullscale 8388608 , unit gal");
					ScaleFactor = 2000;
					FullScale = 8388608;
					Unit = "gal";
				}
				
			}
			else if(0==field.compareToIgnoreCase("Max. Acc. (gal)")){
				
			}
			else if(0==field.compareToIgnoreCase("Last Correction")){
				
			}
			else if(0==field.compareToIgnoreCase("Memo.")){
				int size = SampleRate * Duration;
				if(size>0){
					Data = new int[size];
					ret = size;
				}
				else{
					System.err.println("Sample rate =0 or Duration = 0");
					return -1; //　データが無い！
				}
			}
		}
		return ret;
	}
	/**
	 * データを読み出す
	 * @param str
	 * @param index
	 * @param max
	 * @return
	 */
	private int loadData(String str,int index,int max){
		String[] tok = str.split(" ",-1);
		for(int i=0;i<tok.length;i++){
			if(!tok[i].isEmpty()){
				if(index<max){
					Data[index++] = Integer.valueOf(tok[i]);
				}
			}
		}
		return index;
	}

	private void checkAndCollectData(int index){
		if(Data.length != index){
			int[] a = new int[index];
			System.arraycopy(Data,0,a,0,index);
			System.out.println("Data length modified " + Data.length + " to " + a.length);
			Data = a;
		}
	}

	/**
	 * byte[] からロードする
	 * @param c
	 * @return
	 */
	private int load(byte[] c){
		int state  =0;
		int max = 0;
		int index = 0;
		String str = null;
		try {
			str = new String(c,"UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return -1;
		}
		String[] tok = str.split("[\n\r]");
		for(int i=0;i<tok.length;i++){
			if(!tok[i].isEmpty()){
				if(state == 0){
					int ret = loadHeader(tok[i]);
					if(ret>0){
						max = ret;
						state = 1;
					}					
					else if(ret==-1){
						max = 10000;
						state = 1;
						Data = new int[10000];
					}
				}
				else{
					index = loadData(tok[i],index,max);
				}
			}
		}
		checkAndCollectData(index);
		return 0;
	}
	/**
	 * ファイルから読み出す
	 * @param file
	 * @return
	 * 0=正常終了
	 */
	private int load(String file){
		try {
			File f = new File(file);
			FileReader fr  = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			int state  =0;
			int max = 0;
			int index = 0;
			StationCode = new String("NoName");
			Dir=new String("N-S");
			while(true){
				String str = br.readLine();
				if(str==null) break;
				if(state == 0){
					int ret = loadHeader(str);
					if(ret>0){
						max = ret;
						state = 1;
					}
					else if(ret==-1){
						max = 10000;
						state = 1;
						Data = new int[10000];
					}
				}
				else{
					index = loadData(str,index,max);
				}
			}
			if(StartTime==null){
				StartTime = new wintime(2000,1,1,0,0,0);
			}
			checkAndCollectData(index);
			
		} catch (IOException e) {
			e.printStackTrace();
			return -10; //ファイルが無い、アクセスできない
		}
		return 0;
	}
	// 
	// K-net Ascii のチャンネルＩＤを生成する。
	//  11xx-xxxx-xxxx-xxCC : 
	//    x:StationCodeから生成されるHash値
	//    CC: NS=00,EW=01,UD=10, それ以外11
	private void makeChannelID(){
		if(bChannelReserve) return ;// 既に指定されているなら何もしない
		
		int code = StationCode.hashCode();
		code = ((code >> 24 ^ code>>16 ^code>>8)&0xff);
		code = 0xc000 | (code)<<2;
		int comp = 11;
		if(Dir.compareToIgnoreCase("N-S")==0){
			comp = 0;
		}
		else if(Dir.compareToIgnoreCase("E-W")==0){
			comp = 1;
		}
		else if(Dir.compareToIgnoreCase("U-D")==0){
			comp = 2;
		}
		code |= comp;
		System.out.printf("Loading K-net Ascii : Station=%s Comp.=%s => ChannelID=%04X\n",StationCode,Dir,code);
		Channel = code;
	}
	
}
